package mi.payment.controller;

import com.sunmi.statistics.library.StatisticsManager;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import mi.payment.MyApplication;
import mi.payment.bean.datacollection.PaySummary;
import mi.payment.bean.datacollection.PaySummaryItem;
import mi.payment.constants.PaySummaryConstants;
import mi.payment.db.PayDetailModel;
import mi.payment.db.dao.PayDetail;
import mi.payment.utils.datacollection.PayGatherCollection;
import sunmi.sunmiui.utils.LogUtil;

/**
 * Created by zjr on 2018/1/29.
 * address :zhoujirui@sunmi.com
 * 数据汇总
 */

public class DataCollectionCtrl {
    private static final String TAG = "DataCollectionCtrl";
    //数据汇总上送到dataService
    public static void settlementSum(PayDetailModel PDM, String merchantNum) {
        LogUtil.e(TAG, "setlementSum merchantNum = " + merchantNum);
        //支付宝
        List<PaySummaryItem> alipayConsum = getAmountGroupByDate(PaySummaryConstants.ALIPAYGATHER
                , PDM.getPayDetailByQrCodeTransPlatformAndQrCodeTransType(1, 1)//支付宝消费
        );//支付宝消费汇总

        List<PaySummaryItem> alipayRefund = getAmountGroupByDate(PaySummaryConstants.ALIPAYREFUND,
                PDM.getPayDetailByQrCodeTransPlatformAndQrCodeTransType(1, 2),//支付宝撤销
                PDM.getPayDetailByQrCodeTransPlatformAndQrCodeTransType(1, 3)//支付宝退货
                );//支付宝退款汇总

        //微信
        List<PaySummaryItem> weChatConsum = getAmountGroupByDate(PaySummaryConstants.WECHATGATHER,
                PDM.getPayDetailByQrCodeTransPlatformAndQrCodeTransType(2, 1)//微信消费
                 );//微信消费汇总

        List<PaySummaryItem> wechatRefund = getAmountGroupByDate(PaySummaryConstants.WECHATREFUND,
                PDM.getPayDetailByQrCodeTransPlatformAndQrCodeTransType(2, 2),//微信撤销
                PDM.getPayDetailByQrCodeTransPlatformAndQrCodeTransType(2, 3)//微信退货
        );//微信退款汇总

        //口碑二维码
        List<PaySummaryItem> koubeiConsum = getAmountGroupByDate(PaySummaryConstants.KOUBEIGATHER,
                PDM.getPayDetailByQrCodeTransPlatformAndQrCodeTransType(3, 1)//口碑二维码消费
         );//口碑消费汇总

        List<PaySummaryItem> koubeiRefund = getAmountGroupByDate(PaySummaryConstants.KOUBEIREFUND,
                PDM.getPayDetailByQrCodeTransPlatformAndQrCodeTransType(3, 2),//口碑二维码撤销
                PDM.getPayDetailByQrCodeTransPlatformAndQrCodeTransType(3, 3)//口碑二维码退货
        );//口碑退款汇总

        //银联二维码
        List<PaySummaryItem> unionConsum = getAmountGroupByDate(PaySummaryConstants.UNIONPQYGATHER,
                PDM.getPayDetailByQrCodeTransPlatformAndQrCodeTransType(4, 1)//银联二维码消费
        );//银联消费汇总

        List<PaySummaryItem> unionRefund = getAmountGroupByDate(PaySummaryConstants.UNIONPQYREFUND,
                PDM.getPayDetailByQrCodeTransPlatformAndQrCodeTransType(4, 2),//银联二维码撤销
                PDM.getPayDetailByQrCodeTransPlatformAndQrCodeTransType(4, 3)//银联二维码退货
        );//银联退款汇总

        //银行卡
        List<PaySummaryItem> bankCardConsum = getAmountGroupByDate(PaySummaryConstants.NORFOREIGNGATHER,
                PDM.getSuccessPayDetailByTransactionType(1),//银行卡消费
                PDM.getSuccessPayDetailByTransactionType(6)//银行卡预授权完成
        );//银行卡消费汇总

        List<PaySummaryItem> bankCardRefund = getAmountGroupByDate(PaySummaryConstants.NORFOREIGNREFUND,
                PDM.getSuccessPayDetailByTransactionType(2),//银行卡撤销
                PDM.getSuccessPayDetailByTransactionType(3),//银行卡退货
                PDM.getSuccessPayDetailByTransactionType(7)//银行卡预授权完成撤销
        );//银行卡退款汇总

        List<PaySummaryItem> paySummaryItems = new ArrayList<>();
        paySummaryItems.addAll(alipayConsum);
        paySummaryItems.addAll(alipayRefund);
        paySummaryItems.addAll(weChatConsum);
        paySummaryItems.addAll(wechatRefund);
        paySummaryItems.addAll(koubeiConsum);
        paySummaryItems.addAll(koubeiRefund);
        paySummaryItems.addAll(unionConsum);
        paySummaryItems.addAll(unionRefund);
        paySummaryItems.addAll(bankCardConsum);
        paySummaryItems.addAll(bankCardRefund);
        long time = StatisticsManager.getInstance().getNetTime(MyApplication.getInstance());
        PaySummary paySummary = new PaySummary(merchantNum, time, paySummaryItems);
        PayGatherCollection.getInstance().uploadData(paySummary);
    }

    //按日期汇总结算信息
    private static List<PaySummaryItem> helper(int paySumType, List<PayDetail> payDetails) {
        LogUtil.e(TAG, "paySumType = " + paySumType);
        if (payDetails == null || payDetails.size() <= 0) {
            LogUtil.e(TAG, "payDetails is null");
            return new ArrayList<>();
        }
        LogUtil.e(TAG,"payDetails = " + payDetails.size());
        //思路：因为是按照时间排序的,思路就是把相邻发生在同一天的payDetail累加到一个PaySummaryItem上
        Iterator<PayDetail> I = payDetails.iterator();
        PayDetail next = I.next();
        PaySummaryItem item = new PaySummaryItem(paySumType, 1, String.valueOf(next.getAmount()), next.getTradeDate(), next.getTerminalDate());
        List<PaySummaryItem> info = new ArrayList<>();
        while (I.hasNext()) {
            next = I.next();
            if (next.getTradeDate().equals(item.getDate())) {
                item.setPaySumQuantity(item.getPaySumQuantity() + 1);
                item.setPaySumAmount(String.valueOf(Long.parseLong(item.getPaySumAmount()) + next.getAmount()));
            } else {
                info.add(item);
                item = new PaySummaryItem(paySumType, 1, String.valueOf(next.getAmount()), next.getTradeDate(), next.getTerminalDate());
            }
        }
        //1.如果循环没执行,那么本次添加这个只有一条记录的payDetail
        //2.如果执行了若干次在if true,那么也只是不断在更新这个item,并没有添加，本次添加，这和1的情况类似
        //3.即使执行了若干次if false,那么会添加若干个不同天的item,但是都会产生新的一天的item,本次添加
        info.add(item);
        return info;
    }

    private static List<PaySummaryItem> getAmountGroupByDate(int paySumType, List<PayDetail>... sortedList) {
        LogUtil.e(TAG,"getAmountGroupByDate-->paySumType = " + paySumType);
        if (sortedList == null || sortedList.length <= 0) {
            LogUtil.e(TAG, "sortedList is null");
            return new ArrayList<>();
        }
        List<PayDetail> I = sortedList[0];
        for (int i = 1; i < sortedList.length; i++)//这里还可以加速，不过意义不大，
            I = merge(I, sortedList[i]);//因为段数最多不超过3,进行动态规划的代价可能还更大
        return helper(paySumType, I);
    }

    //将两个分别处于排序状态的列表合并成一个排好序的列表
    private static List<PayDetail> merge(List<PayDetail> A, List<PayDetail> B) {
        if (A.isEmpty() && B.isEmpty()) {
            return new ArrayList<>();
        }
        if (A.isEmpty()) {
            return B;
        }
        if (B.isEmpty()) {
            return A;
        }
        LogUtil.e(TAG,"merge, A.size = " + A.size() +",B.size = " + B.size());
        Iterator<PayDetail> IA = A.iterator();//使用迭代器保证遍历复杂度为O(n)
        Iterator<PayDetail> IB = B.iterator();//如果list底层是LinkedList实现,那么将会有O(n)的访问复杂度,这样可避免
        Integer a = null, b = null;
        PayDetail EA = null, EB = null;
        List<PayDetail> C = new ArrayList<>();
        while ((EA != null || IA.hasNext()) && (EB != null || IB.hasNext())) {//两边都还拥有元素
            if (EA == null) {
                EA = IA.next();
                a = Integer.parseInt(EA.getTradeDate());
            }
            if (EB == null) {
                EB = IB.next();
                b = Integer.parseInt(EB.getTradeDate());
            }
            if (a < b) {
                C.add(EA);
                EA = null;
            } else {
                C.add(EB);
                EB = null;
            }
        }
        if (EA != null) {//为了保证效率，在这种环境下，只能写的这么繁琐
            C.add(EA);
            while (IA.hasNext()){
                C.add(IA.next());
            }
        } else {
            C.add(EB);
            while (IB.hasNext()) {
                C.add(IB.next());
            }
        }
        return C;
    }
}
